<template>
  <view class="parameter-card" :class="{ disabled }">
    <view v-if="title || $slots.desc" class="header">
      <view v-if="title" class="title">
        <text>{{ title }}</text>
        <text v-if="unit" class="unit"> ({{ unit }})</text>
      </view>
      <view v-if="$slots.desc" class="desc">
        <slot name="desc"></slot>
      </view>
    </view>
    <view class="body">
      <!-- Radio -->
      <template v-if="isRadioButton">
        <view class="radio-row">
          <text
            v-for="(option, index) in options"
            :key="index"
            class="radio-option"
            :class="{ active: option.value === value }"
            @click="onRadioSelect(option)"
          >
            <text>{{ option.label }}</text>
          </text>
        </view>
      </template>
      <!-- Checkbox -->
      <template v-else-if="isCheckbox">
        <view class="check-row">
          <view
            v-for="(option, index) in options"
            :key="index"
            class="check-option"
            :class="{ active: isCheckboxActive(option) }"
            @click="onCheckboxSelect(option)"
          >
            <text>{{ getCheckboxLabel(option) }}</text>
            <image
              v-if="option.customOption?.hasArrow"
              class="arrow-icon"
              :src="isCheckboxActive(option) ? '/static/ArrowHighlight.png' : '/static/ArrowDark.png'"
            ></image>
          </view>
        </view>
      </template>
      <!-- Picker -->
      <template v-else-if="isPicker">
        <view class="picker-row">
          <picker-view
            class="picker"
            indicator-class="indicator"
            mask-class="picker-mask"
            :value="[selectedPickerIndex]"
            @change="onPickerChange"
          >
            <picker-view-column>
              <view class="picker-row-column" v-for="option in options" :key="(option.value as string | number)">
                <text
                  class="picker-row-text"
                  :class="{
                    active: paramValue === option.value,
                  }"
                  >{{ option.label }}</text
                >
              </view>
            </picker-view-column>
          </picker-view>
        </view>
      </template>
      <template v-else>
        <slot></slot>
      </template>
    </view>
  </view>
</template>

<script setup lang="ts">
export type CardType = 'Picker' | 'Radio' | 'Checkbox'
export type ValueType = string | number | boolean
export type SelectOptions = { label: string; value: string | number }[]
export type Option = {
  label: string
  value: ValueType
  key: string // Boolean 值或自定义值 使用的 Key 属性
  // 自定义选项
  customOption?: CustomOption
}
export type CustomOption = {
  key: string
  options?: { label: string; value: string }[]
  hasArrow?: boolean
  isActive?: (value: ValueType, option: Option) => boolean
  getLabel?: (value: ValueType, option: Option) => string
  onClick?: (payload: CustomClickPayload) => void
}
export type CustomClickPayload = {
  label?: string
  key: string
  value: ValueType | null
  option: Option
}

/**
 * Props
 */
const props = withDefaults(
  defineProps<{
    title?: string // 标题
    type?: CardType // 不传入指定参数 则使用默认插槽
    optionKey?: string // Key
    value: ValueType | null // 当前值
    unit?: string // 标题旁的显示单位文本
    options?: Option[] // 选项数组
    disabled?: boolean
  }>(),
  {
    value: null,
  }
)
/**
 * Emit
 */
const emit = defineEmits<{
  (e: 'update:value', value: ValueType): void
  (e: 'change', key: string, value: ValueType): void
  (e: 'custom-click', payload: CustomClickPayload): void
}>()

const paramValue = computed({
  get() {
    return props.value
  },
  set(value) {
    if (props.optionKey && value !== null) {
      emit('update:value', value)
      emit('change', props.optionKey, value)
    }
  },
})

/**
 * Radio button 单选
 */
const isRadioButton = computed(() => props.type === 'Radio')
function onRadioSelect(option: Option) {
  paramValue.value = option.value
}

/**
 * Checkbox 多选
 */
const isCheckbox = computed(() => props.type === 'Checkbox')

function isCheckboxActive(option: Option) {
  // 自定义选项
  if (option.customOption) {
    return option.customOption.isActive?.(option.value, option) || false
  }
  return !!option.value
}
function onCheckboxSelect(option: Option) {
  if (option.customOption) {
    const customPayload = {
      key: option.customOption.key,
      value: option.value,
      label: option.label,
      option,
    }
    emit('custom-click', customPayload)
    option.customOption.onClick?.(customPayload)
    return
  }

  // // Checkbox 不修改value属性
  // option.value = !option.value
  const changedValue = !option.value
  emit('change', option.key as string, changedValue)
}
function getCheckboxLabel(option: Option): string {
  return option.customOption?.getLabel?.(option.value, option) || option.label
}

/**
 * Picker 选择
 */
const isPicker = computed(() => props.type === 'Picker')
const selectedPickerIndex = computed(() => {
  if (!props.options) return -1
  return props.options.findIndex((item) => item.value === props.value)
})
function onPickerChange(e: WechatMiniprogram.PickerChange) {
  if (!props.options) return
  const index = e.detail.value[0] as number
  paramValue.value = props.options[index].value
}
</script>

<style lang="less">
.parameter-card {
  width: 100%;
  background-color: #f4f4f6;
  &.disabled > .body {
    filter: opacity(0.6);
  }
  > .header {
    padding: 24rpx;
    font-weight: 500;
    font-size: 32rpx;
    line-height: 44rpx;
    color: rgba(var(--dark-vector), 0.6);
    + .body {
      padding-top: 0;
    }
    .unit {
      font-weight: 500;
      font-size: 22rpx;
    }
    .title {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      overflow: hidden;
      font-size: 28rpx;
      flex: 1;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .extra {
      flex-shrink: 0;
    }
    .desc {
      margin-top: 8rpx;
    }
  }
  > .body {
    padding: 24rpx 0;
  }
  .radio-row,
  .check-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-column: 3;
    gap: 32rpx 0;
    font-weight: 500;
    font-size: 32rpx;
    color: #555d69;
  }
  .radio-option,
  .check-option {
    display: flex;
    justify-content: center;
    align-items: center;
    line-height: 56rpx;
    &.active {
      color: var(--primary-color);
    }
  }
  .picker-row {
    picker-view-column {
      height: 100%;
    }
    .picker {
      width: 100%;
      height: 324rpx;
      background: #f4f4f6;
    }
    .indicator {
      height: 108rpx;
      &,
      &::before,
      &::after {
        border: none;
      }
    }
    .picker-mask {
      background: #f4f4f6;
      z-index: 0;
    }
    .picker-row-column {
      display: flex;
      align-items: center;
      justify-content: center;
      .picker-row-text {
        color: var(--dark-color);
        &.active {
          font-size: 56rpx;
          color: var(--primary-color);
        }
      }
    }
    text-align: center;
  }
  .arrow-icon {
    width: 16rpx;
    height: 26rpx;
    margin-left: 6rpx;
  }
}
</style>
